package com.sheng.leetcode.year2022.month08.day20;

import org.junit.Test;

/**
 * @author liusheng
 * @date 2022/08/20
 *
 * 654. 最大二叉树
 *
 * 给定一个不重复的整数数组 nums 。 最大二叉树 可以用下面的算法从 nums 递归地构建:
 * 创建一个根节点，其值为 nums 中的最大值。
 * 递归地在最大值 左边 的 子数组前缀上 构建左子树。
 * 递归地在最大值 右边 的 子数组后缀上 构建右子树。
 * 返回 nums 构建的 最大二叉树 。
 *
 * 示例 1：
 * 输入：nums = [3,2,1,6,0,5]
 * 输出：[6,3,5,null,2,0,null,null,1]
 * 解释：递归调用如下所示：
 * - [3,2,1,6,0,5] 中的最大值是 6 ，左边部分是 [3,2,1] ，右边部分是 [0,5] 。
 *     - [3,2,1] 中的最大值是 3 ，左边部分是 [] ，右边部分是 [2,1] 。
 *         - 空数组，无子节点。
 *         - [2,1] 中的最大值是 2 ，左边部分是 [] ，右边部分是 [1] 。
 *             - 空数组，无子节点。
 *             - 只有一个元素，所以子节点是一个值为 1 的节点。
 *     - [0,5] 中的最大值是 5 ，左边部分是 [0] ，右边部分是 [] 。
 *         - 只有一个元素，所以子节点是一个值为 0 的节点。
 *         - 空数组，无子节点。
 *
 * 示例 2：
 * 输入：nums = [3,2,1]
 * 输出：[3,null,2,null,1]
 *
 * 提示：
 *
 * 1 <= nums.length <= 1000
 * 0 <= nums[i] <= 1000
 * nums 中的所有整数 互不相同
 *
 * 来源：力扣（LeetCode）
 * 链接：https://leetcode.cn/problems/maximum-binary-tree
 * 著作权归领扣网络所有。商业转载请联系官方授权，非商业转载请注明出处。
 */
public class LeetCode0654 {

    @Test
    public void test01() {
        int[] nums = {3,2,1,6,0,5};
//        int[] nums = {3,2,1};
        TreeNode treeNode = new Solution().constructMaximumBinaryTree(nums);
        System.out.println(treeNode);
    }
}

// Definition for a binary tree node.
class TreeNode {
    int val;
    TreeNode left;
    TreeNode right;
    TreeNode() {}
    TreeNode(int val) { this.val = val; }
    TreeNode(int val, TreeNode left, TreeNode right) {
        this.val = val;
        this.left = left;
        this.right = right;
    }
}

class Solution {
    public TreeNode constructMaximumBinaryTree(int[] nums) {
        int length = nums.length;
        return getTree(nums, 0, length);
    }

    public TreeNode getTree(int[] nums, int left, int right) {
        Integer index = getMax(nums, left, right);
        if (index == null) {
            return null;
        }
        TreeNode treeNode = new TreeNode(nums[index]);
        // 递归左子树
        if (left < index) {
            treeNode.left = getTree(nums, left, index);
        }
        // 递归右子树
        if (index + 1 < right) {
            treeNode.right = getTree(nums, index + 1, right);
        }
        return treeNode;
    }

    /**
     * 获取数组在一段区间内的最大值的索引
     *
     * @param nums 数组
     * @param left 左边界
     * @param right 右边界
     * @return 最大值的索引
     */
    public Integer getMax(int[] nums, int left, int right) {
        int max = left;
        for (int i = left; i < right; i++) {
            if (nums[i] > nums[max]) {
                max = i;
            }
        }
        return max;
    }
}
